#define _CRT_SECURE_NO_WARNINGS 1 
//test C++11
#include <iostream>
using namespace std;
//1:统一的列表初始化
#if 0
class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2022, 1, 1); // old style
	// C++11支持的列表初始化，这里会调用构造函数初始化
	Date d2{ 2022, 1, 2 };
	Date d3 = { 2022, 1, 3 };
	Date d4({ 2022, 1, 3 });
	return 0;
}
#endif

#if 0
int main()
{
	// the type of il is an initializer_list 
	auto il = { 10, 20, 30 };
	cout << typeid(il).name() << endl;
	return 0;
}

int main()
{
	vector<int> v = { 1,2,3,4 };
	list<int> lt = { 1,2 };
	// 这里{"sort", "排序"}会先初始化构造一个pair对象
	map<string, string> dict1 = { {"sort", "排序"}, {"insert", "插入"} };
	map<string, string> dict2{ {"sort", "排序"}, {"insert", "插入"} };
	map<string, string> dict3({ {"sort", "排序"}, {"insert", "插入"} });

	// 使用大括号对容器赋值
	v = { 10, 20, 30 };
	return 0;
}
#endif

//2:声明
#if 0
//auto
int main()
{
	int i = 10;
	auto p = &i;
	auto pf = strcpy;
	cout << typeid(p).name() << endl;
	cout << typeid(pf).name() << endl;
	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	cout << typeid(it).name() << endl;
	return 0;
}
#endif

#if 0
//decltype
// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
	decltype(t1 + t2) ret;
	cout << typeid(ret).name() << endl;
}
int main()
{
	const int x = 1;
	double y = 2.2;
	decltype(x * y) ret; // ret的类型是double
	decltype(&x) p = &x;
	// p的类型是int*
	auto pp = p;
	cout << typeid(ret).name() << endl;
	cout << typeid(p).name() << endl;
	cout << typeid(pp).name() << endl;
	F("abc", 'abc');
	return 0;
}
#endif

//3:
//右值引用和移动语义
//左值引用和右值引用


#if 0
//左值引用
int main()
{
	// 以下的p、b、c、*p都是左值
	int* p = new int(0);
	int b = 1;
	const int c = 2;
	// 以下几个是对上面左值的左值引用
	int*& rp = p;
	int& rb = b;
	const int& rc = c;
	int& pvalue = *p;
	return 0;
}
#endif

#if 0
//右值引用
// 右值引用，给右值取别名
// 纯右值 （内置类型的）
// 将亡值 （自定义类型的）

// 右值引用意义
// 引用的意义是减少拷贝，提高效率
// 左值引用的场景
int main()
{
	double x = 1.1, y = 2.2;
	// 以下几个都是常见的右值
	10;
	x + y;
	fmin(x, y);
	// 以下几个都是对右值的右值引用
	int&& rr1 = 10;
	double&& rr2 = x + y;
	double&& rr3 = fmin(x, y);
	// 这里编译会报错：error C2106: “=”: 左操作数必须为左值
	/*
	10 = 1;
	x + y = 1;
	fmin(x, y) = 1;*/
	return 0;
}
#endif

#if 0
//右值可以出现在赋值符号的右边，但是不能出现出现在赋值符号的左边，右值不能
//取地址。
int main()
{
	double x = 1.1, y = 2.2;
	int&& rr1 = 10;
	const double&& rr2 = x + y;
	rr1 = 20;
	//rr2 = 5.5;  // 报错 const double&& rr2 = x + y; const!!!!!!!!!!
	return 0;
}
#endif

#if 0
//左值引用总结：
//1. 左值引用只能引用左值，不能引用右值。
//2. 但是const左值引用既可引用左值，也可引用右值。

int main()
{
	// 左值引用只能引用左值，不能引用右值。
	int a = 10;
	int& ra1 = a;
	// ra为a的别名
	//int& ra2 = 10;   // 编译失败，因为10是右值
	// const左值引用既可引用左值，也可引用右值。
	const int& ra3 = 10;
	const int& ra4 = a;
	return 0;
}
#endif

#if 0
//右值引用总结：
//1. 右值引用只能右值，不能引用左值。
//2. 但是右值引用可以move以后的左值。
int main()
{
	// 右值引用只能右值，不能引用左值。
	int&& r1 = 10;
	// error C2440: “初始化”: 无法从“int”转换为“int &&”
	// message : 无法将左值绑定到右值引用
	int a = 10;
	//int&& r2 = a;//error
	// 右值引用可以引用move以后的左值
	int&& r3 = std::move(a);
	return 0;
}
#endif

#if 0
void func1(bit::string s)
{}
void func2(const bit::string& s)
{}
int main()
{
	bit::string s1("hello world");
	// func1和func2的调用我们可以看到左值引用做参数减少了拷贝，提高效率的使用场景和价值
	func1(s1);
	func2(s1);
	func2(move(s1));
	// string operator+=(char ch)  传值返回存在深拷贝
	// string& operator+=(char ch) 传左值引用没有拷贝提高了效率
	s1 += '!';
	return 0;
}
#endif

#if 0
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }

void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
template<typename T>
void PerfectForward(T&& t)
{
	Fun(t);
}
int main()
{
	PerfectForward(10);
	int a;
	PerfectForward(a);
	// 右值
	// 左值
	PerfectForward(std::move(a)); // 右值
	const int b = 8;
	PerfectForward(b);
	// const 左值
	PerfectForward(std::move(b)); // const 右值
	return 0;
}
#endif

#if 0
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
template<typename T>
void PerfectForward(T&& t)
{
	Fun(t);
}
int main()
{
	PerfectForward(10);
	int a;
	PerfectForward(a);
	// 右值
	// 左值
	PerfectForward(std::move(a)); // 右值
	const int b = 8;
	PerfectForward(b);
	// const 左值
	PerfectForward(std::move(b)); // const 右值
	return 0;
}
#endif

#if 0

int main() {
	bit::string s1("hello world");
	bit::string s2(s1);
	bit::string s3(move(s1));
	bit::string&& s4 = move(s3);
	bit::string s5 = move(s4);
	s5 = move(s2);
	return 0;
}
#endif

#if 0
//右值引用具有左值属性
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
//template<typename T>
//void PerfectForward(T&& t)
//{
//	Fun(t);
//}

//完美转发
//template<typename T>
//void PerfectForward(T&& t)
//{
//	Fun(forward<T>(t));
//}

//模板转换
template<typename T>
void PerfectForward(T&& t)
{
	Fun((T&&)t);
}
int main()
{
	PerfectForward(10);
	int a;
	PerfectForward(a);
	// 右值
	// 左值
	PerfectForward(std::move(a)); // 右值
	const int b = 8;
	PerfectForward(b);
	// const 左值
	PerfectForward(std::move(b)); // const 右值
	return 0;
}
#endif
//C++11: 新增了两个：移动构造函数和移动赋值运算符重载。
//针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下：
//如果你没有自己实现移动构造函数，且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任
//意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数，对于内置类
//型成员会执行逐成员按字节拷贝，自定义类型成员，则需要看这个成员是否实现移动构造，
//如果实现了就调用移动构造，没有实现就调用拷贝构造。
//如果你没有自己实现移动赋值重载函数，且没有实现析构函数 、拷贝构造、拷贝赋值重载中
//的任意一个，那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数，对于内
//置类型成员会执行逐成员按字节拷贝，自定义类型成员，则需要看这个成员是否实现移动赋
//值，如果实现了就调用移动赋值，没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造
//	完全类似)
//	如果你提供了移动构造或者移动赋值，编译器不会自动提供拷贝构造和拷贝赋值。
//#define _CRT_SECURE_NO_WARNINGS 1 
//#include"string1.hpp"
//#include"list.hpp"
//using namespace bit1;

#if 0
void test_list1()
{
	bit2::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	bit2::list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		*it += 10;
		cout << *it << " ";
		++it;
	}
	cout << endl;

	lt.push_front(10);
	lt.push_front(20);
	lt.push_front(30);

	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	lt.pop_back();
	lt.pop_back();
	lt.pop_front();
	lt.pop_front();

	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

struct A
{
	int _a1;
	int _a2;

	A(int a1 = 0, int a2 = 0)
		:_a1(a1)
		, _a2(a2)
	{}
};

void test_list2()
{
	bit2::list<A> lt;
	A aa1(1, 1);
	A aa2 = { 1, 1 };
	lt.push_back(aa1);
	lt.push_back(aa2);
	lt.push_back(A(2, 2));
	lt.push_back({ 3, 3 });
	lt.push_back({ 4, 4 });

	A* ptr = &aa1;
	(*ptr)._a1;
	ptr->_a1;

	bit2::list<A>::iterator it = lt.begin();
	while (it != lt.end())
	{
		//*it += 10;
		//cout << (*it)._a1 << ":" << (*it)._a2 << endl;
		cout << it->_a1 << ":" << it->_a2 << endl;
		cout << it.operator->()->_a1 << ":" << it.operator->()->_a2 << endl;

		++it;
	}
	cout << endl;
}

void PrintList(const bit2::list<int>& clt)
{
	bit2::list<int>::const_iterator it = clt.begin();
	while (it != clt.end())
	{
		//*it += 10;

		cout << *it << " ";
		++it;
	}
	cout << endl;
}

void test_list3()
{
	bit2::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	bit2::PrintList(lt);

	bit2::list<int> lt1(lt);
	bit2::PrintList(lt1);
}

void test_list4() {
	bit1::string s1 = "hello";
	bit1::string s2 = move(s1);
	bit1::string&& s = forward<bit1::string&&>(move(s2));
	bit1::string s3 = forward<bit1::string&&>(move(s));
	bit1::string s4(s3);
}


int main() {
	test_list4();
	return 0;
}
#endif

#if 0
class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}

	/*Person(const Person& p)
	:_name(p._name)
,_age(p._age)
{}*/
/*Person& operator=(const Person& p)
{
if(this != &p)
{
_name = p._name;
_age = p._age;
}
return *this;
}*/
/*~Person()
{}*/
private:
	bit1::string _name;
	int _age;
};
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = std::move(s1);
	Person s4;
	s4 = std::move(s2);
	return 0;
}
#endif

#if 0
class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}
	Person(const Person& p)
		:_name(p._name)
		, _age(p._age)
	{}
	Person(Person&& p) = default;
private:
	bit1::string _name;
	int _age;
};
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = std::move(s1);
	return 0;
}
#endif

#if 0
class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}
	Person(const Person& p) = delete;
private:
	bit1::string _name;
	int _age;
};
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = move(s1);
}
#endif

//参数包
// 递归终止函数
#if 0
template <class T>
void ShowList(const T& t)
{
	cout << t << endl;
}
// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{
	cout << value << " ";
	ShowList(args...);
}

int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}
#endif

#if 0
template <class T>
void PrintArg(T t)
{
	cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { (PrintArg(args), 0)... };
	cout << endl;
}

int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}
#endif

//emplace_back()系列
#if 0
#include<utility>
#include<list>
int main()
{
	std::list< std::pair<int, char> > mylist;
	// emplace_back支持可变参数，拿到构建pair对象的参数后自己去创建对象
   // 那么在这里我们可以看到除了用法上，和push_back没什么太大的区别
	mylist.emplace_back(10, 'a');
	mylist.emplace_back(20, 'b');
	mylist.emplace_back(make_pair(30, 'c'));
	mylist.push_back(make_pair(40, 'd'));
	mylist.push_back({ 50, 'e' });
	for (auto e : mylist)
		cout << e.first << ":" << e.second << endl;
	return 0;
}
#endif

#if 0
#include<functional>
//包装器
template<class F, class T>
T useF(F f, T x)
{
	static int count = 0;
	cout << "count:" << ++count << endl;
	cout << "count:" << &count << endl;

	return f(x);
}

double f(double i)
{
	return i / 2;
}
struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};

int main()
{
	// 函数名
	cout << useF(f, 11.11) << endl;
	// 函数对象
	cout << useF(Functor(), 11.11) << endl;
	// lambda表达式
	cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;
	cout << endl << endl;

	std::function<double(double)> func1 = f;
	cout << useF(func1, 11.11) << endl;
	// 函数对象
	std::function<double(double)> func2 = Functor();
	cout << useF(func2, 11.11) << endl;
	// lamber表达式
	std::function<double(double)> func3 = [](double d)->double { return d /
		4; };
	cout << useF(func3, 11.11) << endl;

	return 0;
}
#endif

#if 0
#include<functional>
// 包装成员函数指针
class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	// 成员函数的函数指针  &类型::函数名
	function<int(int, int)> fc1 = &Plus::plusi;
	cout << fc1(1, 2) << endl;

	//不要忽this指针
	function<double(Plus*, double, double)> fc2 = &Plus::plusd;
	Plus plus;
	cout << fc2(&plus, 1.1, 2.2) << endl;

	function<double(Plus, double, double)> fc3 = &Plus::plusd;
	cout << fc3(Plus(), 1.1, 2.2) << endl;
	Plus p;
	auto fc4 = std::bind(&Plus::plusd, &p/*this*/, placeholders::_1, placeholders::_2);
	cout << fc4(1, 2) << endl;

	return 0;
}
#endif

#if 0
#include<functional>
#include<string>
class Sub
{
public:
	Sub(int x)
		:_x(x)
	{}

	int sub(int a, int b)
	{
		return (a - b) * _x;
	}

private:
	int _x;
};

void fx(const std::string& name, int x, int y)
{
	cout << name << "->[" << "血量:" << x << ",蓝:" << y << ']' << endl;
}

template<class T>
void fy(int n)
{
	T* p = new T[n];
}

// 调整可调用对象的参数个数或者顺序

int main()
{
	//auto f1 = Sub;
	//cout << f1(10, 5) << endl;

	// 调整顺序
	/*auto f2 = bind(Sub, placeholders::_1, placeholders::_2);
	cout << f2(10, 5) << endl;*/

	//cout << typeid(f1).name() << endl;
	//cout << typeid(f2).name() << endl;


	auto f3 = bind(&Sub::sub, placeholders::_1, placeholders::_2, placeholders::_3);
	cout << f3(Sub(1), 10, 5) << endl;

	Sub sub(1);
	cout << f3(&sub, 10, 5) << endl;

	// 绑定，调整参数个数
	auto f4 = bind(&Sub::sub, Sub(1), placeholders::_1, placeholders::_2);
	cout << f4(10, 5) << endl;

	auto f5 = bind(&Sub::sub, &sub, placeholders::_2, placeholders::_1);
	cout << f5(10, 5) << endl;

	/*fx("王昭君", 80, 20);
	fx("王昭君", 85, 10);
	fx("王昭君", 99, 0);
	fx("王昭君", 99, 80);

	fx("亚瑟", 99, 80);
	fx("亚瑟", 91, 80);
	fx("亚瑟", 5, 80);*/

	auto f6 = bind(fx, "王昭君", placeholders::_1, placeholders::_2);

	f6(80, 20);
	f6(85, 10);
	f6(99, 0);
	f6(99, 80);

	auto f7 = bind(fx, "亚瑟", placeholders::_1, placeholders::_2);

	f7(80, 20);
	f7(85, 10);
	f7(99, 0);
	f7(99, 80);

	//auto f8 = bind(fx, placeholders::_1, 80, placeholders::_2);
	function<void(std::string, int)> f8 = bind(fx, placeholders::_1, 80, placeholders::_2);
	f8("武则天", 50);
	f8("韩信", 40);

	cout << typeid(f7).name() << endl;
	cout << typeid(f8).name() << endl;

	map<std::string, function<int(int, int)>> opFuncMap = {
		   {"+", [](int a, int b) {return a + b; }},
		   {"-", bind(&Sub::sub, Sub(10), placeholders::_1, placeholders::_2)},
		   {"*", [](int a, int b) {return a * b; }},
		   {"/", [](int a, int b) {return a / b; }}
	};

	fy<int>(10);

	return 0;
}
#endif

#if 0
#include <algorithm>
#include <unordered_map>
#include <string>
#include<functional>
#include<vector>


int main() {
	vector<int> arr1({ 2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19 });
	vector<int> arr2({ 2, 1, 4, 3, 9, 6 });
	unordered_map<int, int> rank;
	for (int i = 0; i < arr2.size(); i++) {
		rank[arr2[i]] = i;
	}

	auto lambda = [&](int& x, int& y)
		{
			if (rank.count(x))
				return rank.count(y) ? rank[x] < rank[y] : true;

			else
				return rank.count(y) ? false : x < y;

		};
	std::sort(arr1.begin(), arr1.end(), lambda);


	for (auto e : arr1) cout << e << " ";
	cout << typeid(lambda).name() << endl;
	cout << endl;
	return 0;
}
#endif

#if 0
// 使用举例
#include <functional>
int Plus(int a, int b)
{
	return a / b;
}
class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	//表示绑定函数plus 参数分别由调用 func1 的第一，二个参数指定
	std::function<int(int, int)> func1 = std::bind<int>(Plus, placeholders::_1,
		placeholders::_2);
	//auto func1 = std::bind(Plus, placeholders::_1, placeholders::_2);
	//func2的类型为 function<void(int, int, int)> 与func1类型一样
   //表示绑定函数 plus 的第一，二为： 1， 2
	auto  func2 = std::bind(Plus, 1, 2);
	cout << typeid(func1(1, 2)).name() << func1(1, 2) << endl;
	cout << func2() << endl;
	Sub s;
	// 绑定成员函数
	std::function<int(int, int)> func3 = std::bind(&Sub::sub, s,
		placeholders::_1, placeholders::_2);
	std::function<int(int, int)> func4 = std::bind(&Sub::sub, s,
		placeholders::_2, placeholders::_1);
	cout << func3(1, 2) << endl;
	cout << func4(1, 2) << endl;
	return 0;
}
#endif

#if 0
#include<thread>
int main() {
	std::cout << _getpid() << std::endl;
	std::thread t1;//当创建一个线程对象后，没有提供线程函数，该对象实际没有对应任何线程。
	std::cout << t1.get_id() << std::endl;
	std::cout << typeid(t1.get_id()).name() << std::endl;
	return 0;
}
#endif

#if 0
#include<iostream>
#include<functional>
#include<thread>
#include<mutex>
using namespace std;
mutex mtx;

class TF
{
public:
	void ThreadFunc(int a)
	{
		mtx.lock();
		std::cout << "Thread1" << " " << a << endl;
		mtx.unlock();
	}

	void operator()()
	{
		mtx.lock();
		std::cout << "Thread3" << endl;
		mtx.unlock();
	}
};
int main()
{
	// 线程函数为函数对象
	TF tf;
	thread t3(tf);
	// 线程函数为函数指针
	auto func = std::bind(&TF::ThreadFunc, &tf, std::placeholders::_1);
	thread t1(func, 10);
	//线程函数为lambda表达式
	thread t2([] {
		mtx.lock();
		std::cout << "Thread2" << endl;
		mtx.unlock();
		}
	);
	t1.join();
	t2.join();
	t3.join();
	mtx.lock();

	std::cout << "Main thread!" << endl;
	mtx.unlock();

	return 0;
}
#endif

#if 0
#include<iostream>
#include<functional>
#include<thread>
#include<mutex>
using namespace std;

int main() {
	int a = 10;
	int b = 20;
	cout << "a:" << &a << endl; cout << "b:" << &b << endl;
	auto func2 = [&]() {int a = 0; int b = 1; cout << "a:" << &a << endl; cout << "b:" << &b << endl; return a + b; };
	cout << func2() << endl;
	auto func = [&]() {cout << "a:" << &a << endl; cout << "b:" << &b << endl; return a + b; };
	cout << func() << endl;
	return 0;
}
#endif

#if 0
#include<iostream>
#include<functional>
#include<thread>
#include<mutex>
using namespace std;

void ThreadFunc1(int& x)
{
	x += 10;
}
void ThreadFunc2(int* x)
{
	*x += 10;
}
int main()
{
	int a = 10;
	//在线程函数中对a修改，不会影响外部实参，因为：线程函数参数虽然是引用方式，但其实际引用的是线程栈中的拷贝
	thread t1(ThreadFunc1, a);//报错！！！！
	t1.join();
	cout << a << endl;
	//如果想要通过形参改变外部实参时，必须借助std::ref()函数
	thread t2(ThreadFunc1, std::ref(a));
	t2.join();
	cout << a << endl;
	//地址的拷贝
	thread t3(ThreadFunc2, &a);
	t3.join();
	cout << a << endl;
	return 0;
}
#endif


#if 0

// bind example
#include <iostream>     // std::cout
#include <functional>   // std::bind

// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide(double x, double y) { return x / y; }

struct MyPair {
	double a, b;
	double multiply() { return a * b; }
};

int main() {
	using namespace std::placeholders;    // adds visibility of _1, _2, _3,...

	// binding functions:
	auto fn_five = std::bind(my_divide, 10, 2);               // returns 10/2
	std::cout << fn_five() << '\n';                          // 5

	auto fn_half = std::bind(my_divide, _1, 2);               // returns x/2
	std::cout << fn_half(10) << '\n';                        // 5

	auto fn_invert = std::bind(my_divide, _2, _1);            // returns y/x
	std::cout << fn_invert(10, 2) << '\n';                    // 0.2

	auto fn_rounding = std::bind<int>(my_divide, _1, _2);     // returns int(x/y)
	std::cout << "!!!!" << fn_rounding(10, 3) << '\n';                  // 3

	MyPair ten_two{ 10,2 };

	// binding members:
	auto bound_member_fn = std::bind(&MyPair::multiply, _1); // returns x.multiply()
	std::cout << bound_member_fn(ten_two) << '\n';           // 20

	auto bound_member_data = std::bind(&MyPair::a, ten_two); // returns ten_two.a
	std::cout << bound_member_data() << '\n';                // 10

	return 0;
}
#endif

#if 0
#include<thread>
void ThreadFunc1(int& x)
{
	x += 10;
}
void ThreadFunc2(int* x)
{
	*x += 10;
	cout << x << endl;
}

int main() {
	int a = 10;
	thread t1(ThreadFunc1, ref(a));
	t1.join();
	cout << a << endl;
	cout << "thread 1,done !" << endl;

	thread t2(ThreadFunc2, &a);
	t2.join();
	cout << &a << endl;
	cout << "thread 2,done !" << endl;


	return 0;
}
#endif

#if 0
//保证临界资源的操作具有原子性
// 1：枷锁 2：对临界资源进行原子性修饰 // atmoic<T> t;
#include <iostream>
#include <thread>
#include<mutex>
#include<atomic>
#include"LockGuard.hpp"
using namespace std;

mutex gmtx;
unsigned long sum = 0;
atomic<unsigned long> sum1 = 0;
unsigned long sum2 = 0;

void fun(size_t num)
{
	//gmtx.lock();
	LockGuard mtx(&gmtx);
	for (size_t i = 0; i < num; ++i)
		sum++;
	//gmtx.unlock();
}

void  fun1(size_t num)
{
	for (size_t i = 0; i < num; ++i)
		sum1++;
}

int main()
{
	cout << "Before joining,sum = " << sum << std::endl;
	thread t1(fun, 10000000);
	thread t2(fun, 10000000);
	t1.join();
	t2.join();
	cout << "After joining,sum = " << sum << std::endl;

	cout << "Before joining,sum1 = " << sum1 << std::endl;
	thread t3(fun1, 10000000);
	thread t4(fun1, 10000000);
	t3.join();
	t4.join();
	cout << "After joining,sum1 = " << sum1 << std::endl;

	cout << "Before joining,sum2 = " << sum2 << std::endl;

	return 0;
}
#endif

#if 0
#include <thread>
#include <mutex>
int number = 0;
mutex g_lock;

int ThreadProc1()
{
	for (int i = 0; i < 100; i++)
	{
		g_lock.lock();
		++number;
		cout << "thread 1 :" << number << endl;
		g_lock.unlock();
	}
	return 0;
}

int ThreadProc2()
{
	for (int i = 0; i < 100; i++)
	{
		g_lock.lock(); 
		--number;
		cout << "thread 2 :" << number << endl;
		g_lock.unlock();
	}
	return 0;
}

int main()
{
	thread t1(ThreadProc1);
	thread t2(ThreadProc2);
	t1.join();
	t2.join();
	cout << "number:" << number << endl;
	//system("pause");
	return 0;
}
#endif

class A {
public:
	A() {}
	~A() {}
private:
	int a1;
	int a2;
};
// 仿函数的删除器:当智能指针管理不是 new 出来的对象时就需要到删除器。
template<class T>
struct FreeFunc {
	void operator()(T* ptr)
	{
		cout << "free:" << ptr << endl;
		free(ptr);
	}
};

template<class T>
struct DeleteArrayFunc {
	void operator()(T* ptr)
	{
		cout << "delete[]" << ptr << endl;
		delete[] ptr;
	}
};
int main()
{
	//仿函数形式的删除器
	FreeFunc<int> freeFunc;
	std::shared_ptr<int> sp1((int*)malloc(4), freeFunc);
	DeleteArrayFunc<int> deleteArrayFunc;
	std::shared_ptr<int> sp2((int*)malloc(4), deleteArrayFunc);

	//lambda形式的删除器
	std::shared_ptr<A> sp4(new A[10], [](A* p) {cout << "delete[]" << p << endl; delete[] p; });
	std::shared_ptr<FILE> sp5(fopen("test.txt", "w"), [](FILE* p)
		{cout << "close[]" << p << endl; fclose(p); });
	return 0;
}